<template>
  <div class="select-wrap" v-if="disabled">
    <div class="select disabled" ref="selectRef">
      <div class="selector">{{ value }}</div>
      <div class="icon">
        <slot name="icon">
          <IconDown :size="14" />
        </slot>
      </div>
    </div>
  </div>
  <Popover 
    class="select-wrap"
    trigger="click" 
    v-model:value="popoverVisible" 
    placement="bottom"
    :contentStyle="{
      padding: 0,
      boxShadow: '0 6px 16px 0 rgba(0, 0, 0, 0.08)',
    }" v-else>
    <template #content>
      <div class="tree-box" :style="{ width: width + 2 + 'px' }">
        <div v-for="item in props.data" :key="item[props.valueProps]">
          <div class="label-box">
            <span class="icon-box" v-if="item.children.length">
              <IconFolderOpen style="font-size: 18px;" v-if="show" @click="changeShow(false)"></IconFolderOpen>
              <IconFolderClose style="font-size: 18px;" v-else @click="changeShow(true)"></IconFolderClose>
            </span>
            <span class="icon-box" v-else>
              <IconDocDetail style="font-size: 18px;"></IconDocDetail>
            </span>
            <span class="label-text">{{ item[props.labelProps] }}</span>
          </div>
          <div v-show="item.children.length && show">
            <div class="child-label-box" v-for="child in item.children" :key="child[props.valueProps]" >
              <span class="icon-box" v-if="child.children.length">
                <IconFolderClose style="font-size: 18px;" v-if="false"></IconFolderClose>
                <IconFolderOpen style="font-size: 18px;" v-else></IconFolderOpen>
              </span>
              <span class="icon-box" v-else>
                <IconDocDetail style="font-size: 18px;"></IconDocDetail>
              </span>
              <span class="label-text">{{ child[props.labelProps] }}</span>
            </div>
          </div>
          
        </div>
      </div>
    </template>
    <div class="select" ref="selectRef">
      <div :class="{'selector': true, 'placeholder': !props.value }">{{ !!props.value ? '' : props.pleaceholder }}</div>
      <div class="icon">
        <slot name="icon">
          <IconDown :size="14" />
        </slot>
      </div>
    </div>
  </Popover>
</template>

<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue'
import Popover from './Popover.vue'

interface SelectOption {
  label?: string
  value?: string | number
  disabled?: boolean,
  children: SelectOption,
  [propN: string]:any //  任意属性
}

const props = withDefaults(defineProps<{
  labelProps: string
  valueProps: string
  value: string | number
  data: SelectOption[]
  disabled?: boolean,
  pleaceholder: string
}>(), {
  disabled: false,
  labelProps: 'label',
  valueProps: 'value',
})

const show = ref(false)

const emit = defineEmits<{
  (event: 'update:value', payload: string | number): void
}>()

const popoverVisible = ref(false)
const selectRef = ref<HTMLElement>()
const width = ref(0)

const updateWidth = () => {
  if (!selectRef.value) return
  width.value = selectRef.value.clientWidth
}
const resizeObserver = new ResizeObserver(updateWidth)
onMounted(() => {
  if (!selectRef.value) return
  resizeObserver.observe(selectRef.value)
})
onUnmounted(() => {
  if (!selectRef.value) return
  resizeObserver.unobserve(selectRef.value)
})

const changeShow = (flag: boolean) => {
  show.value = flag
}

const handleSelect = (option: SelectOption) => {
  if (option.disabled) return

  emit('update:value', option.value as string)
  popoverVisible.value = false
}

</script>

<style lang="scss" scoped>
.select {
  width: 100%;
  height: 32px;
  padding-right: 32px;
  border-radius: $borderRadius;
  transition: border-color .25s;
  font-size: 13px;
  user-select: none;
  background-color: #fff;
  border: 1px solid #d9d9d9;
  position: relative;
  cursor: pointer;

  &:not(.disabled):hover {
    border-color: $themeColor;
  }

  &.disabled {
    background-color: #f5f5f5;
    border-color: #dcdcdc;
    color: #b7b7b7;
    cursor: default;
  }
  .placeholder{
    color: #b7b7b7;
  }

  .selector {
    min-width: 50px;
    height: 30px;
    line-height: 30px;
    padding-left: 10px;
    @include ellipsis-oneline();
  }
}
.tree-box {
  max-height: 260px;
  padding: 5px;
  overflow: auto;
  text-align: left;
  font-size: 13px;
  user-select: none;
  .label-text{
    padding-left: 5px;
  }
  .label-box{
    height: 32px;
    line-height: 32px;
    padding: 0 5px;
    display:flex;
    align-items: center;
    border-radius: $borderRadius;
    cursor: pointer;
    @include ellipsis-oneline();

    &.disabled {
      color: #b7b7b7;
      cursor: default;
    }
    &:not(.disabled, .selected):hover {
      background-color: rgba($color: #666, $alpha: .05);
    }

    &.selected {
      background-color: rgba($color: $themeColor, $alpha: .05);
    }
  }
  .child-label-box{
    height: 32px;
    line-height: 32px;
    padding: 0 5px 0 22px;
    display:flex;
    align-items: center;
    border-radius: $borderRadius;
    cursor: pointer;
    @include ellipsis-oneline();

    &.disabled {
      color: #b7b7b7;
      cursor: default;
    }
    &:not(.disabled, .selected):hover {
      background-color: rgba($color: #666, $alpha: .05);
    }

    &.selected {
      background-color: rgba($color: $themeColor, $alpha: .05);
    }
  }
}
.option {
  height: 32px;
  line-height: 32px;
  padding: 0 5px;
  border-radius: $borderRadius;
  cursor: pointer;
  @include ellipsis-oneline();

  &.disabled {
    color: #b7b7b7;
    cursor: default;
  }
  &:not(.disabled, .selected):hover {
    background-color: rgba($color: #666, $alpha: .05);
  }

  &.selected {
    background-color: rgba($color: $themeColor, $alpha: .05);
  }
}
.icon {
  width: 32px;
  height: 30px;
  color: #bfbfbf;
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>

